package com.zzh.lib.core.utils;


import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by ZZH on 3/19/21.
 *
 * @Date: 3/19/21
 * @Email: zzh_hz@126.com
 * @QQ: 1299234582
 * @Author: zzh
 * @Description: 定时任务。单例模式
 */
public class HTaskUtils {

    public static final String DEFAULT_SINGLE_TASK = "h_default_single_task";
    public static final String DEFAULT_TASK = "h_default_task";

    private static final ConcurrentHashMap<String, HTaskUtils> mCurrentTask;
    private static final LinkedBlockingQueue<Runnable> mQueue;

    static {
        mCurrentTask = new ConcurrentHashMap<>();
        mQueue = new LinkedBlockingQueue<>();
    }

    /**
     * 核心线程数量
     */
    public static final int DEFAULT_CORE_POOL_SIZE = 8;
    private int corePoolSize = 1;

    private ScheduledThreadPoolExecutor mScheduledExecutorService;

    private HTaskUtils(int corePoolSize) {
        this.corePoolSize = corePoolSize;
        initScheduledExecutorService(corePoolSize);
    }

    /**
     * 获取默认线程池
     *
     * @return 默认单对列
     */
    public static HTaskUtils getSingleInstance() {
        return getInstance(DEFAULT_SINGLE_TASK, 1);
    }

    /**
     * 获取默认的多任务线程池
     *
     * @return 默认多任务执行
     */
    public static HTaskUtils getDefaultInstance() {
        return getInstance(DEFAULT_TASK, DEFAULT_CORE_POOL_SIZE);
    }

    /**
     * 获取默认线程池
     *
     * @return 线程池
     */
    public static Executor getDefaultExecutor() {
        return getDefaultInstance().mScheduledExecutorService;
    }

    /**
     * 根据key获取任务对列
     *
     * @param key key
     * @return HTaskUtils实例
     */
    public static HTaskUtils getInstance(String key, int corePoolSize) {
        HTaskUtils taskUtils = mCurrentTask.get(key);
        if (taskUtils == null) {
            synchronized (HTaskUtils.class) {
                if (taskUtils == null) {
                    taskUtils = new HTaskUtils(corePoolSize);
                    mCurrentTask.put(key, taskUtils);
                }
            }
        }

        return taskUtils;
    }

    private void initScheduledExecutorService(int corePoolSize) {
        if (mScheduledExecutorService == null) {
            mScheduledExecutorService = new ScheduledThreadPoolExecutor(corePoolSize);
        }
    }


    /**
     * 延迟执行任务
     *
     * @param task 执行任务
     * @param ms   延迟毫秒值
     */
    public RunnableScheduledFuture<?> execute(Runnable task, long ms) {
        if (mScheduledExecutorService == null) {
            initScheduledExecutorService(corePoolSize);
        }
        return (RunnableScheduledFuture<?>) mScheduledExecutorService.schedule(task, ms, TimeUnit.MILLISECONDS);
    }

    /**
     * 延迟执行任务
     *
     * @param task 执行任务, 添加到队列
     */
    public RunnableScheduledFuture<?> execute(Runnable task) {
        return execute(task, 0);
    }

    public int size() {
        return mScheduledExecutorService.getQueue().size();
    }

    /**
     * 延迟执行任务
     *
     * @param task  任务
     * @param delay 延迟执行时间
     * @param unit  延迟执行时间单位
     */
    public RunnableScheduledFuture<?> execute(Runnable task, long delay, TimeUnit unit) {
        if (mScheduledExecutorService == null) {
            initScheduledExecutorService(corePoolSize);
        }
        return (RunnableScheduledFuture<?>) mScheduledExecutorService.schedule(task, delay, unit);
    }

    /**
     * 移除定时任务
     *
     * @param task 需要移除的定时任务
     */
    public boolean removeTask(RunnableScheduledFuture task) {
        if (mScheduledExecutorService != null) {
            boolean remove = mScheduledExecutorService.remove(task);
            LogUtils.e("-------:  移除定时任务: " + remove);
            return remove;
        }
        return false;
    }

    /**
     * 释放资源
     *
     * @param key 释放指定的线程池资源
     */
    public static void release(String key) {
        if (mCurrentTask.containsKey(key)) {
            HTaskUtils hTaskUtils = mCurrentTask.remove(key);
            hTaskUtils.destroy();
            hTaskUtils = null;
        }
    }

    public synchronized static void release() {
        Set<String> keySet = mCurrentTask.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            release(next);
        }
    }


    /**
     * 释放资源
     */
    private synchronized void destroy() {
        if (mScheduledExecutorService != null) {
            mScheduledExecutorService.shutdownNow();
            mScheduledExecutorService = null;
        }
    }
}
